package com.strawcom.charmring.bluetooth;

import android.annotation.TargetApi;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.bluetooth.*;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.location.Location;
import android.os.*;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import com.amap.api.location.AMapLocation;
import com.amap.api.location.AMapLocationListener;
import com.amap.api.location.LocationManagerProxy;
import com.amap.api.location.LocationProviderProxy;
import com.android.volley.Request.Method;
import com.android.volley.toolbox.ByteArrayPool;
import com.strawcom.charmring.App;
import com.strawcom.charmring.C;
import com.strawcom.charmring.R;
import com.strawcom.charmring.bean.Calories;
import com.strawcom.charmring.bean.DailySummary;
import com.strawcom.charmring.bean.http.BaseResponse;
import com.strawcom.charmring.bean.http.PostEmergencyAlarmRequest;
import com.strawcom.charmring.bluetooth.RingBleController.*;
import com.strawcom.charmring.util.*;
import com.strawcom.charmring.util.HttpUtil.ResponeListener;
import m.framework.network.ByteArrayPart;
import org.apache.http.util.ByteArrayBuffer;
import org.kymjs.kjframe.utils.SystemTool;

import java.io.*;
import java.nio.ByteBuffer;
import java.util.*;
import java.util.zip.CRC32;

import static com.strawcom.charmring.bluetooth.RingBleController.*;

/**
 * charmring戒指蓝牙服务
 * 
 * @author WangPeng
 */
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2)
public class RingBleService extends Service {

	public static boolean sIsUpdating;

	public static String sBleAdress;

	/**Srun edit at 2015.9.1 start **/
	private boolean mIsFirstRun = false;
	private boolean mIsLocationManagerRunning = false;
	private Double mGeoLat;
	private Double mGeoLng;
	private float mAccuracy;
	/**Srun edit at 2015.9.1 end **/

	/**Srun edit at 2015.9.2 start **/
	private static final int ALARM_LEAST_TIME = 30000;
	/**Srun edit at 2015.9.2 end **/

	private final IBinder mBinder = new LocalBinder();

	public class LocalBinder extends Binder {
		public RingBleService getService() {
			return RingBleService.this;
		}
	}

	public BluetoothDevice mDevice;

	public BluetoothDevice getDevice() {
		return mDevice;
	}

	@Override public IBinder onBind(Intent intent) {
		return mBinder;
	}

	/** 设备连接时发送的广播信号 */
	public static final String ACTION_GATT_CONNECTED = "com.strawcom.charmring.bluetooth.ACTION_GATT_CONNECTED";
	/** 设备断开时发送的广播信号 */
	public static final String ACTION_GATT_DISCONNECTED = "com.strawcom.charmring.bluetooth.ACTION_GATT_DISCONNECTED";
	/** 广播携带信息key */
	public static final String EXTRA_DATA = "com.strawcom.charmring.bluetooth.EXTRA_DATA";
	/** 设备上报晃动程度溢出阀值时发出的广播信号 */
	public static final String ACTION_GATT_MOTION_THRESHOLD_OVERFLOW = "com.strawcom.charmring.bluetooth.ACTION_GATT_MOTION_THRESHOLD_OVERFLOW";
	/** 设备上报晃动程度溢出阀值时发出的广播信号-用于告警信息 */
	public static final String ACTION_GATT_MOTION_ALARM = "com.strawcom.charmring.bluetooth.ACTION_GATT_MOTION_ALARM";
	/** 设备上报记步信息是的广播信号 用于刷新运动相关界面 */
	public static final String ACTION_GATT_EXERCISE_INFO_REPORT = "com.strawcom.charmring.bluetooth.ACTION_GATT_EXERCISE_INFO_REPORT";
	/** 读取未知的服务或者特征值时发出的广播信号 */
	public static final String ACTION_GATT_UNKOWN_INFO = "com.strawcom.charmring.bluetooth.ACTION_GATT_UNKOWN_INFO";

	public static final String ACTION_GATT_MESSAGE_INFO = "com.strawcom.charmring.bluetooth.ACTION_GATT_MESSAGE_INFO";
	public static final String ACTION_GATT_UPGRADE_INFO = "com.strawcom.charmring.bluetooth.ACTION_GATT_UPGRADE_INFO";
	public static final String ACTION_GATT_BATTERY_INFO = "com.strawcom.charmring.bluetooth.ACTION_GATT_BATTERY_INFO";
	public static final String ACTION_GATT_VERSION_INFO = "com.strawcom.charmring.bluetooth.ACTION_GATT_VERSION_INFO";

	/** 当前设备的连接状态 true connected; false disconnected; */
	private boolean currConnectionState;
	/** 主动点击断开标示，当设备被动断开连接时进行自动重连 */
	private boolean positiveDisconnect = false;

	public void setPositiveDisconnect(boolean positiveDisconnect) {
		this.positiveDisconnect = positiveDisconnect;
	}

	private InfoRecorder recorder = new InfoRecorder();
	
	/** 连接的设备是否更换，作用于记步统计。见setCurrAddress */
	private boolean connectedDeviceChanged = false;
	/** 当前连接地址 */
	private String currAddress;
	private BluetoothManager bluetoothManager;
	private BluetoothAdapter bluetoothAdapter;
	private final Map<String, BluetoothGatt> bluetoothGattMap = new HashMap<String, BluetoothGatt>();
	private final BluetoothGattCallback bluetoothGattCallback = new BluetoothGattCallback() {
		@Override public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
			LogUtil.d("RingBleService onConnectionStateChange() status:" + status + ",newState:" + newState);
			String bleAddress = gatt.getDevice().getAddress();
			if (newState == BluetoothProfile.STATE_CONNECTED) {
				if (status == 0) {
					recorder.recordConnectInfo("收到设备成功连接上的广播");
					// 记录为上次连接的MAC
					PreferenceUtil.write(RingBleService.this, C.sp.ring_ble_last_address, bleAddress);

					gatt.discoverServices();
					bluetoothGattMap.put(bleAddress, gatt);
					
					broadcastConnect(bleAddress);

					positiveDisconnect = false;

					mDevice = gatt.getDevice();
					
				}
			}
			else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
				if (status == 0) {
					recorder.recordConnectInfo("收到设备断开连接的广播");
					broadcastDisconnect(gatt.getDevice().getAddress());
					mDevice = null;
					gatt.disconnect();
					gatt.close();
					// 断开后移除gatt
					bluetoothGattMap.remove(gatt.getDevice().getAddress());
					// 如果是被动断开就自动重连
					if (!positiveDisconnect) {
						recorder.recordConnectInfo("设备被动掉线..尝试重连");
						autoConnectLastAddress();
					}
				}
			}
		}

		@Override public void onServicesDiscovered(BluetoothGatt gatt, int status) {
			LogUtil.d("RingBleService onServicesDiscovered() status:" + status);
			if (status == BluetoothGatt.GATT_SUCCESS) {
				setCurrAddress(gatt.getDevice().getAddress());
				recorder.recordConnectInfo("读取设备服务完成，初始化配置设备");
				initGattProperties(gatt.getDevice().getAddress());
			}
			else {
				LogUtil.e("RingBleService onServicesDiscovered() fetch service fail!");
			}

		}

		/** 订阅之后，设备主动上报的特征变更信息 */
		@Override public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
			LogUtil.d("RingBleService onCharacteristicChanged()");
			if (sIsUpdating) {
				return;
			}
			byte[] value = characteristic.getValue();
			if (value != null) {
				LogUtil.e("RingBleService value:" + RingBleController.bytesToHex(value));
				LogUtil.e("RingBleService value:" + characteristic.getUuid().toString());
				recorder.recordConnectInfo("设备主动上报:" + RingBleController.bytesToHex(value));
			}
			else {
				LogUtil.e("RingBleService empty value");
				recorder.recordConnectInfo("设备主动上报:null");
			}
			rbController.dealRingMessage(gatt.getDevice().getAddress(), characteristic.getValue());
		}

		/** 当主动读取设备特征值时的回调 */
		@Override public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
			LogUtil.d("RingBleService onCharacteristicRead() status:" + status);
			if (sIsUpdating) {
				return;
			}
			byte[] value = characteristic.getValue();
			if (value != null) {
				LogUtil.e("RingBleService value:" + RingBleController.bytesToHex(value));
				LogUtil.e("RingBleService characteristic:"+characteristic.getUuid().toString());
			}
			else {
				LogUtil.e("RingBleService empty value");
			}

			//
			if (CHARACTERISTIC_BATTERY.equals(characteristic.getUuid())) {
				broadcastBatteryInfo(value[0]);
			}
			else if (CHARACTERISTIC_6_SPOTA_SERV_STATUS.equals(characteristic.getUuid())) {
				LogUtil.e("RingBleService 更新的订阅回复！！！！！！！！！！！！！");
			}else if (characteristic.getUuid().toString().equals(CHARACTERISTIC_3_SPOTA_MEM_INFO.toString())) {
				System.out.println("升级状态:" + RingBleController.bytesToHex(value));
			}
		}

		@Override public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
			String value = RingBleController.bytesToHex(characteristic.getValue());
			if (sIsUpdating) {
				return;
			}
			LogUtil.d("RingBleService onCharacteristicWrite() value:" + value + ",status:" + status);
			if (updateState != UPGRADE_UNKOWN) {
				requestDeviceUpgrade(gatt.getDevice().getAddress(), 0);
				if (characteristic.getUuid() == CHARACTERISTIC_3_SPOTA_MEM_INFO) {
					System.out.println("asdfasdjfalsdkfj");
				}
			}
		}

	};
	
	
	

	/** 发送获取了电量信息的广播 */
	private void broadcastBatteryInfo(int battery) {
		final Intent intent = new Intent(ACTION_GATT_BATTERY_INFO);
		intent.putExtra(EXTRA_DATA, battery);
		sendBroadcast(intent);
	}

	/** 发送读取未知的服务或者特征值的广播 */
	private void broadcastUnkownInfo(String address, String action) {
		LogUtil.e("RingBleService request unkown info - address:" + address + ",action:" + action);
		final Intent intent = new Intent(ACTION_GATT_UNKOWN_INFO);
		intent.putExtra(EXTRA_DATA, action);
		sendBroadcast(intent);
	}

	/** 发送设备连接断开的广播 */
	private void broadcastDisconnect(String address) {
		if (address != null && address.equals(currAddress)) {
			currConnectionState = false;
			if (positiveDisconnect) {
				setCurrAddress(""); // 如果是主动断开，就清空上次的连接信息
			}
			final Intent intent = new Intent(ACTION_GATT_DISCONNECTED);
			intent.putExtra(EXTRA_DATA, address);
			sendBroadcast(intent);
		}
	}

	/** 发送设备连接成功的广播 */
	private void broadcastConnect(String address) {
		if (address != null) {
			currConnectionState = true;
			setCurrAddress(address);

			final Intent intent = new Intent(ACTION_GATT_CONNECTED);
			intent.putExtra(EXTRA_DATA, address);
			sendBroadcast(intent);
		}
	}

	private void broadcast(String action) {
		final Intent intent = new Intent(action);
		sendBroadcast(intent);
	}

	@Override public void onCreate() {
		super.onCreate();
		// 初始化蓝牙组件
		if (!init()) {
			stopSelf();
			return;
		}
		// 蓝牙交互信息记录
		recorder.recordConnectInfo("蓝牙服务启动成功");
		// 来电监听
		listenTheRemindCall();
		// 读取设定参数
		readBleParams();
		// 自动重连
		autoConnectLastAddress();
		
		// test记步消息
//		 mHandler.postDelayed(testStepRecord, 6000);
		
//		DataSupport.delete(Calories.class, 7);
//		DataSupport.delete(Calories.class, 8);
//		DataSupport.delete(Calories.class, 9);
	}

//	private Runnable testStepRecord = new Runnable() {
//		@Override public void run() {
//			 dbRecordInfoToDailySummary(getCurrAddress(), true, (int)
//			 (System.currentTimeMillis() / 1000 -
//			 RingBleController.offsetTime), Calories.TYPE_RUN, 1, 160 + r.nextInt(40));
//			 broadcast(ACTION_GATT_EXERCISE_INFO_REPORT);
//			 mHandler.postDelayed(testStepRecord, 60000);
//			 LogUtil.e("RingBleService test exercise record");
//		}
//	};

	private final Random r = new Random();

	@Override public void onDestroy() {
		super.onDestroy();

		// 释放定位资源
		releaseAmapLocManager();
		// 断开并关闭所有连接
		for (String address : bluetoothGattMap.keySet()) {
			disconnectAndClose(address);
		}
		// 释放所有消息
		mHandler.removeCallbacksAndMessages(null);
		
		recorder.recordConnectInfo("释放定位资源,断开并关闭所有连接,释放所有消息");
		recorder.recordConnectInfo("蓝牙服务已销毁");
	}

	/** 初始化蓝牙组件 */
	private boolean init() {
		if (bluetoothManager == null) {
			bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
			if (bluetoothManager == null) {
				LogUtil.e("RingBleService init() bluetoothManager fail");
				return false;
			}
		}

		bluetoothAdapter = bluetoothManager.getAdapter();
		if (bluetoothAdapter == null) {
			LogUtil.e("RingBleService init() bluetoothAdapter fail");
			return false;
		}
		LogUtil.i("RingBleService init() success");
		return true;
	}

	/** 如果没有任何连接，关闭蓝牙服务 */
	public void stopIfDisconnect() {
		if (bluetoothGattMap.size() < 1) {
			stopSelf();
		}
	}

	/** 蓝牙是否启用 */
	public boolean isEnable() {
		return bluetoothAdapter.isEnabled();
	}

	@SuppressWarnings("deprecation") public void startLeScan(BluetoothAdapter.LeScanCallback callback) {
		// 扫描之前先释放其它Gatt ，因为只做单连接。
		for (String address : bluetoothGattMap.keySet()) {
			disconnectAndClose(address);
		}
		recorder.recordConnectInfo("开始扫描周围设备...");
		LogUtil.e("RingBleService startLeScan() callback:" + callback);
		if (callback != null) {
			bluetoothAdapter.startLeScan(callback);
		}
	}

	@SuppressWarnings("deprecation") public void stopLeScan(BluetoothAdapter.LeScanCallback callback) {
		LogUtil.e("RingBleService stopLeScan() callback:" + callback);
		recorder.recordConnectInfo("停止扫描周围设备...");
		if (callback != null) {
			bluetoothAdapter.stopLeScan(callback);
		}
	}

	public boolean isCurrConnectionState() {
		return currConnectionState;
	}

	/** 重连上次的MAC地址 */
	public void autoConnectLastAddress() {
		// 读取上次地址
		String lastAddress = PreferenceUtil.readString(this, C.sp.ring_ble_address);
		LogUtil.e("autoConnectLastAddress() try to connect last address :" + lastAddress + ",currConnectionState:" + currConnectionState);
		if (!TextUtils.isEmpty(lastAddress) && !currConnectionState) {
			// 连接
			recorder.recordConnectInfo("重新连接上次设备["+lastAddress+"]");
			connect(lastAddress);
		}
		else {
			LogUtil.e("autoConnectLastAddress() last address empty");
		}
	}

	public boolean connect(String address) {
		if (TextUtils.isEmpty(address)) {
			LogUtil.e("RingBleService connect() empty address");
			return false;
		}

		BluetoothGatt bluetoothGatt = getBluetoothGattByAddress(address);
		if (bluetoothGatt != null) {
			if (bluetoothGatt.connect()) {
				LogUtil.i("RingBleService connect() use an existing bluetoothGatt for connection. success");

				// positiveDisconnect = false;
				// return true;
				disconnectAndClose(address);
				bluetoothGattMap.remove(address);
			}
			else {
				LogUtil.e("RingBleService connect() fail ?");
				disconnectAndClose(address);
				bluetoothGattMap.remove(address);
			}
		}

		final BluetoothDevice device = bluetoothAdapter.getRemoteDevice(address);
		bluetoothGatt = device.connectGatt(this, false, bluetoothGattCallback);
		if (device == null) {
			LogUtil.e("RingBleService device not found. unable to connect.");
			return false;
		}

		BluetoothGattCharacteristic characteristic = new BluetoothGattCharacteristic(CHARACTERISTIC_6_SPOTA_SERV_STATUS, BluetoothGattCharacteristic.PROPERTY_NOTIFY, BluetoothGattCharacteristic.PERMISSION_READ);
		bluetoothGatt.setCharacteristicNotification(characteristic, true);

		BluetoothGattDescriptor descriptor = characteristic.getDescriptor(CHARACTERISTIC_CLIENT_NOTIFICATION);
		if (descriptor == null) {
			LogUtil.e("RingBleService setCharacteristicNotification() empty descriptor ");
			return false;
		}
		descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
		bluetoothGatt.writeDescriptor(descriptor);

		if (bluetoothGatt == null) {
			LogUtil.e("RingBleService gatt create fail! . unable to connect.");
			return false;
		}
		LogUtil.i("RingBleService connect() use a new bluetoothatt for connection. success");
		recorder.recordConnectInfo("向设备["+address+"]发起连接请求");
		sBleAdress = address;
		return true;
	}

	public void disconnectAndClose(final String address) {
		recorder.recordConnectInfo("断开连接并关闭释放设备[" + address+"]");
		final BluetoothGatt bluetoothGatt = getBluetoothGattByAddress(address);
		if (bluetoothGatt != null) {
			restoreGattProperties(address);

			new Handler().postDelayed(new Runnable() {
				@Override public void run() {
					bluetoothGatt.disconnect();
					bluetoothGatt.close();
					
					bluetoothGattMap.remove(address);
					if (address.equals(currAddress)) currAddress = "";
				}
			}, 400);
		}
	}

	public void setCurrAddress(String address) {
		LogUtil.i("setCurrAddress:" + address);
		connectedDeviceChanged = !(currAddress != null && currAddress.equals(address));

		currAddress = address;
		PreferenceUtil.write(this, C.sp.ring_ble_address, currAddress == null ? "" : currAddress);
	}

	public String getCurrAddress() {
		return currAddress;
	}

	/** 刚刚连接上设备后，需要和设备进行的交互逻辑 */
	private void initGattProperties(final String address) {
		LogUtil.e("initGattProperties");
		recorder.recordConnectInfo("刚刚连接上设备后，对设备进行配置");
		// 订阅设备上传的运动消息
		setCharacteristicNotification(address, SERVICE_MESSAGE, CHARACTERISTIC_RECEIVE, true);
		recorder.recordConnectInfo("订阅运动信息消息");
		// 订阅设备上传的升级消息
		setCharacteristicNotification(address, SERVICE_UPGRADE, CHARACTERISTIC_6_SPOTA_SERV_STATUS, true);
		recorder.recordConnectInfo("订阅升级信息消息");
		
		// 连接时触发设备闪灯
		mHandler.postDelayed(new Runnable() {
					@Override public void run() {
						// 开启设备闪光灯
						requestCallsRemind(address, true);
						mHandler.postDelayed(new Runnable() {
							@Override public void run() {
								// 关闭设备闪光灯
								requestCallsRemind(address, false);
							}
						}, 3000);
					}
		}, 200);
		// 还原门限阀值 - 高门限
		mHandler.postDelayed(new Runnable() {
			@Override public void run() {
				requestMotionThreshold(address, false);
			}
		}, 600);
		
		// 记步消息 ：如果当前关联上的设备不是原来的设备,通知设备清除全部的缓存运动数据
		if (connectedDeviceChanged) {
			LogUtil.i("connect device changed!!! reset records");
			mHandler.postDelayed(new Runnable() {
				@Override public void run() {
					requestExerciseInfoReset(address);
				}
			}, 1000);
		}
		
		// 当设备刚刚和手机关联上时，重设时戳为手机APP获取当前的时间值
				mHandler.postDelayed(new Runnable() {
					@Override public void run() {
						requestAmendTimestamp(address);
					}
				}, 1400);
				
		// 基础设置
		mHandler.postDelayed(new Runnable() {
			@Override public void run() {
				requestBasicSettings(address, callsRemind, (byte) lightTime, locationShare, lossPrevent, (byte) lossFlashTime);
			}
		}, 1800);
	}

	private void restoreGattProperties(String address) {

	}

	private BluetoothGatt getBluetoothGattByAddress(String address) {
		if (TextUtils.isEmpty(address)) {
			LogUtil.e("RingBleService getBluetoothGattByAddress() empty address ");
			return null;
		}
		return bluetoothGattMap.get(address);
	}

	/**
	 * 读取设备信息
	 * 
	 * @param address
	 *            设备MAC地址
	 * @param serviceId
	 *            设备服务
	 * @param characteristicId
	 *            设备特征值
	 * @return 设备特征值的当前值
	 */
	private byte[] read(String address, UUID serviceId, UUID characteristicId) {
		final BluetoothGatt bluetoothGatt = getBluetoothGattByAddress(address);
		if (bluetoothGatt == null) {
			LogUtil.e("RingBleService read() empty bluetoothGatt ");
			return null;
		}
		final BluetoothGattService service = bluetoothGatt.getService(serviceId);
		if (service == null) {
			LogUtil.e("RingBleService read() empty service ");
			return null;
		}
		final BluetoothGattCharacteristic characteristic = service.getCharacteristic(characteristicId);
		if (characteristic == null) {
			LogUtil.e("RingBleService read() empty characteristic ");
			return null;
		}
		bluetoothGatt.readCharacteristic(characteristic);
		return characteristic.getValue();
	}

	/** 读取电量 */
	private byte[] readBattery(String address, UUID characteristicId) {
		byte[] battery = read(address, SERVICE_BATTERY, characteristicId);
		if (battery == null) {
			broadcastUnkownInfo(address, ACTION_GATT_BATTERY_INFO);
		}
		return battery;
	}

	/**
	 * 写入设备信息
	 * 
	 * @param address
	 *            设备MAC地址
	 * @param serviceId
	 *            设备服务
	 * @param characteristicId
	 *            设备特征值
	 * @param value
	 *            设备特征值对应的当前值
	 * @return
	 */
	private boolean write(String address, UUID serviceId, UUID characteristicId, byte[] value) {
		final BluetoothGatt bluetoothGatt = getBluetoothGattByAddress(address);
		if (bluetoothGatt == null) {
			LogUtil.e("RingBleService write() empty bluetoothGatt ");
			return false;
		}
		final BluetoothGattService service = bluetoothGatt.getService(serviceId);
		if (service == null) {
			LogUtil.e("RingBleService write() empty service ");
			return false;
		}
		final BluetoothGattCharacteristic characteristic = service.getCharacteristic(characteristicId);
		if (characteristic == null) {
			LogUtil.e("RingBleService write() empty characteristic ");
			return false;
		}

		characteristic.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT);
		characteristic.setValue(value);
		bluetoothGatt.writeCharacteristic(characteristic);
		return true;
	}

	/**
	 * 对服务SERVICE_MESSAGE写入信息<br>
	 * <b>作用于消息交互<b>
	 * 
	 * @param address
	 *            设备MAC地址
	 * @param characteristicId
	 *            特征值
	 * @param value特征值当前值
	 * @return
	 */
	private boolean writeMessage(String address, UUID characteristicId, byte[] value) {
		boolean result = write(address, SERVICE_MESSAGE, characteristicId, value);
		if (!result) {
			broadcastUnkownInfo(address, ACTION_GATT_MESSAGE_INFO);
		}
		return result;
	}

	/**
	 * 对服务SERVICE_MESSAGE写入信息<br>
	 * <b>作用于设备升级<b>
	 * 
	 * @param address
	 *            设备MAC地址
	 * @param characteristicId
	 *            特征值
	 * @param value特征值当前值
	 * @return
	 */
	private boolean writeUpgrade(String address, UUID characteristicId, byte[] value) {
		boolean result = write(address, SERVICE_UPGRADE, characteristicId, value);
		if (!result) {
			broadcastUnkownInfo(address, ACTION_GATT_UPGRADE_INFO);
		}
		return result;
	}

	/** 清空设备内部的运动信息 */
	public void requestExerciseInfoReset(String address) {
		recorder.recordConnectInfo("发送消息：清空设备内部的运动信息");
		LogUtil.i("RingBleService requestExerciseInfoReset() " + address);
		writeMessage(address, CHARACTERISTIC_SEND, VALUE_RESET_RECORDS);
	}

	/** 同步更新设备内部时间戳 */
	public void requestAmendTimestamp(String address) {
		recorder.recordConnectInfo("发送消息：更新设备内部时间戳");
		LogUtil.i("RingBleService requestAmendTimestamp() " + address);
		byte[] mTime = Arrays.copyOf(VALUE_SET_TIMESTAMP, VALUE_SET_TIMESTAMP.length);
		int iTime = (int) ((System.currentTimeMillis() - FormatUtil.parseDate("20000101", "yyyyMMdd").getTime()) / 1000);
		byte[] bTime = ConvertHelper.int2ByteArray(iTime, false);
		for (int i = 0; i < bTime.length; i++) {
			mTime[i + 1] = bTime[i];
		}
		writeMessage(address, CHARACTERISTIC_SEND, mTime);
	}

	/** 发送消息：来电提醒- true打开;false关闭 */
	public void requestCallsRemind(String address, boolean call) {
		recorder.recordConnectInfo("发送消息：" + (call ? "开启" : "关闭")+"设备闪光灯");
		LogUtil.i("RingBleService requestCallsRemind() " + address + ", call:" + call);
		byte[] value = call ? VALUE_CALL_REMIND_OPEN : VALUE_CALL_REMIND_CLOSE;
		writeMessage(address, CHARACTERISTIC_SEND, value);
	}

	/** 发送消息：基础设置 */
	public void requestBasicSettings(String address, boolean callsRemind, byte callRemindTime, boolean locationShare, boolean lossPrevent,
			byte lossFlashTime) {
		recorder.recordConnectInfo("发送消息：基础设置[来电提醒"+callsRemind+";提醒时长"+callRemindTime+";告警"+locationShare+";防丢"+lossPrevent+";闪光时长"+lossFlashTime+";]");
		LogUtil.i("RingBleService requestBasicSettings() " + address + ", callsRemind:" + callsRemind + ",callRemindTime:" + callRemindTime
				+ ",locationShare:" + locationShare + ",lossPrevent:" + lossPrevent + ",lossFlashTime:" + lossFlashTime);
		byte lossPreventDelayed = 5;
		byte[] value = Arrays.copyOf(VALUE_BASIC_SETTINGS, VALUE_BASIC_SETTINGS.length);
		value[1] = (byte) (callsRemind ? 0x01 : 0x00);
		value[2] = callRemindTime;
		value[3] = (byte) (locationShare ? 0x01 : 0x00);
		value[4] = (byte) (lossPrevent ? 0x01 : 0x00);
		value[5] = lossFlashTime;
		value[6] = lossPreventDelayed;
		writeMessage(address, CHARACTERISTIC_SEND, value);

	}

	/** 发送消息：晃动门限阀值 */
	public void requestMotionThreshold(String address, boolean open) {
		recorder.recordConnectInfo("发送消息：还原门限阀值-" + (open ? "低门限":"高门限"));
		LogUtil.i("RingBleService requestMotionThreshold() " + address + ", open:" + open);
		byte[] value = open ? VALUE_MOTION_THRESHOLD_SENSITIVE : VALUE_MOTION_THRESHOLD_SLOW;
		writeMessage(address, CHARACTERISTIC_SEND, value);
	}

	/** 发送消息：将运动报告全部取到APP上 */
	public void requestExerciseInfo(String address) {
		// APP切换到前台抓取数据全部精确到秒。
		requestExerciseInfo(address, true);
	}

	/** 发送消息：请求运动信息 */
	private void requestExerciseInfo(String address, boolean fetchAll) {
		recorder.recordConnectInfo("发送消息：请求运动信息");
		LogUtil.i("RingBleService requestExerciseInfo() " + address);
		byte[] value = fetchAll ? VALUE_GET_REPORTS_ALL : VALUE_GET_REPORTS_MIN;
		writeMessage(address, CHARACTERISTIC_SEND, value);
	}

	/** 发送消息：读取电量 */
	public void requestBatteryInfo(String address) {
		recorder.recordConnectInfo("发送消息：请求电量");
		LogUtil.i("RingBleService requestBatteryInfo() " + address);
		readBattery(address, CHARACTERISTIC_BATTERY);
	}

	/** 发送消息：读取闪灯时长 */
	public void requestLightTime(String address, byte lightTime) {
		recorder.recordConnectInfo("发送消息：获取闪灯时长");
		LogUtil.i("RingBleService requestLightTime() " + address + ", open:" + lightTime);
		byte[] value = VALUE_CALL_REMIND_LIGHT_TIME;
		value[2] = lightTime;
		writeMessage(address, CHARACTERISTIC_SEND, value);
	}
	/**和Ring升级有关的属性*/
	int sendImgPos;            /**当前发送数据位置*/
	public static int updateState = UPGRADE_UNKOWN;   /**升级状态机*/

	/**每个Block的大小，必须大于64字节，并且是20的整数倍*/
	int kRingUpdateImgBlockLen = 240;
	int kRingUpdateImgElemLen = 20;

	byte[] curBytesBlock;
	public static byte[] getBytes(String filePath){
		byte[] buffer = null;
		try {
			File file = new File(filePath);
			FileInputStream fis = new FileInputStream(file);
			ByteArrayOutputStream bos = new ByteArrayOutputStream(1000);
			byte[] b = new byte[1000];
			int n;
			while ((n = fis.read(b)) != -1) {
				bos.write(b, 0, n);
			}
			fis.close();
			bos.close();
			buffer = bos.toByteArray();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return buffer;
	}
	byte[] ringImgDta;
	private void sendDataBlock(int startP,String address) throws IOException {
		if (ringImgDta == null) {
			ringImgDta = getBytes(RingBleController.obtainBleUpdateFile(this).getPath());
			byte[] tempRingImgDta = new byte[ringImgDta.length + 1];
			for (int i = 0; i < ringImgDta.length; i++) {
				tempRingImgDta[i] = ringImgDta[i];
			}
			tempRingImgDta[ringImgDta.length] = CRC8.calcCrc8(ringImgDta);
			ringImgDta = tempRingImgDta;
		}
		int bytesRemain = ringImgDta.length - startP;
		System.out.println("bytesRemain:"+bytesRemain);
		int bytesBlock = kRingUpdateImgBlockLen;

		if (bytesRemain == 0) {
			isTransform = false;
			elementStartPosition = 0;
			requestDeviceUpgrade(address,0);
			return ;
		}

		if (bytesRemain < bytesBlock) {
			bytesBlock = bytesRemain;
		}

		byte[] imgBlock = new byte[bytesBlock];

		for (int i = 0; i < bytesBlock; i++) {
			imgBlock[i] = ringImgDta[startP + i];
		}

		System.out.println("patch len is :"+bytesBlock);
		curBytesBlock = imgBlock;
		bytesBlockLen = bytesBlock;
		configPatchLen(bytesBlock,address);
		sendImgPos = startP + bytesBlock;
		elementStartPosition = 0;
	}
	int bytesBlockLen;
	int elementStartPosition;
	private void sendDataElement(String address) throws IOException {
		byte[] imgBlock = null;
		if (bytesBlockLen >= kRingUpdateImgElemLen) {
			imgBlock = new byte[kRingUpdateImgElemLen];
		} else {
			imgBlock = new byte[bytesBlockLen];
		}

		for (int i = 0; i < imgBlock.length; i++) {
			imgBlock[i] = curBytesBlock[elementStartPosition + i];
		}
		elementStartPosition += imgBlock.length;
		bytesBlockLen -= imgBlock.length;
		if (bytesBlockLen == 0) {
			sendDataBlock(sendImgPos,address);
//			return;
		}
		BluetoothGatt bluetoothGatt = getBluetoothGattByAddress(address);
		BluetoothGattService service = bluetoothGatt.getService(SERVICE_UPGRADE);
		BluetoothGattCharacteristic characteristic = service.getCharacteristic(CHARACTERISTIC_5_SPOTA_PATCH_DATA);
		characteristic.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE);
		characteristic.setValue(imgBlock);
		bluetoothGatt.writeCharacteristic(characteristic);
	}
	public static boolean isTransform = false;

	 public void requestDeviceUpgrade(String address, int step) {
		if (!isTransform||updateState == UPGRADE_UNKOWN) {
			updateState++;
		}

		recorder.recordConnectInfo("发送消息：设备升级[步骤" + updateState + "]");
		LogUtil.i("RingBleService requestDeviceUpdate() " + address + ",step:" + updateState);
		byte[] value = null;
		switch (updateState) {
			case UPGRADE_1:
				value = VALUE_1_SPOTA_MEM_DEV;
				writeUpgrade(address, CHARACTERISTIC_1_SPOTA_MEM_DEV, value);
				break;
			case UPGRADE_2:
				value = VALUE_2_SPOTA_GPIO_MAP;
				writeUpgrade(address, CHARACTERISTIC_2_SPOTA_GPIO_MAP, value);
				break;
			case UPGRADE_3:
				try {
					sendDataBlock(sendImgPos,address);
				} catch (IOException e) {
					e.printStackTrace();
				}
				break;

			case UPGRADE_4:
				isTransform = true;
				try {
					sendDataElement(address);
				} catch (IOException e) {
					e.printStackTrace();
				}
				break;
			case UPGRADE_5:
				//TODO:效验
				BluetoothGatt bluetoothGatt = getBluetoothGattByAddress(address);
				BluetoothGattService service = bluetoothGatt.getService(SERVICE_UPGRADE);
				BluetoothGattCharacteristic characteristic = service.getCharacteristic(CHARACTERISTIC_3_SPOTA_MEM_INFO);

				characteristic.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT);
				bluetoothGatt.readCharacteristic(characteristic);
				break;
			case UPGRADE_6:
				//TODO:结束传输
				writeUpgrade(address, CHARACTERISTIC_1_SPOTA_MEM_DEV, value);
				break;
//			case UPGRADE_7:
//				//TODO:添加重启
////				writeUpgrade(address, CHARACTERISTIC_1_SPOTA_MEM_DEV, reboot);
//				break;
		}
	}

	/**
	 * Enables or disables notification on a give characteristic.
	 * 
	 * @param address
	 *            device address
	 * @param characteristicId
	 *            Characteristic to act on.
	 * @param enabled
	 *            If true, enable notification. False otherwise.
	 */
	public boolean setCharacteristicNotification(String address, UUID serviceId, UUID characteristicId, boolean enabled) {
		final BluetoothGatt bluetoothGatt = getBluetoothGattByAddress(address);
		if (bluetoothGatt == null) {
			LogUtil.e("RingBleService setCharacteristicNotification() empty bluetoothGatt ");
			return false;
		}
		final BluetoothGattService service = bluetoothGatt.getService(serviceId);
		if (service == null) {
			LogUtil.e("RingBleService setCharacteristicNotification() empty service ");
			broadcastUnkownInfo(address, serviceId.toString());
			return false;
		}
		final BluetoothGattCharacteristic characteristic = service.getCharacteristic(characteristicId);
		if (characteristic == null) {
			LogUtil.e("RingBleService setCharacteristicNotification() empty characteristic ");
			broadcastUnkownInfo(address, serviceId.toString());
			return false;
		}
		LogUtil.d("RingBleService setCharacteristicNotification() " + address + ", enabled:" + enabled);
		bluetoothGatt.setCharacteristicNotification(characteristic, enabled);
		BluetoothGattDescriptor descriptor = characteristic.getDescriptor(CHARACTERISTIC_CLIENT_NOTIFICATION);
		if (descriptor == null) {
			LogUtil.e("RingBleService setCharacteristicNotification() empty descriptor ");
			return false;
		}
		descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
		bluetoothGatt.writeDescriptor(descriptor);
		return true;
	}

	private void listenTheRemindCall() {
		recorder.recordConnectInfo("来电监听");
		TelephonyManager tpm = (TelephonyManager) this.getSystemService(Context.TELEPHONY_SERVICE);
		tpm.listen(new PhoneStateListener() {
			@Override public void onCallStateChanged(int state, String incomingNumber) {
				super.onCallStateChanged(state, incomingNumber);
				if (callsRemind) {
					switch (state) {
					case TelephonyManager.CALL_STATE_RINGING:
						for (String address : bluetoothGattMap.keySet()) {
							requestCallsRemind(address, true);
						}
						break;
					case TelephonyManager.CALL_STATE_OFFHOOK:
					case TelephonyManager.CALL_STATE_IDLE:
						for (String address : bluetoothGattMap.keySet()) {
							requestCallsRemind(address, false);
						}
						break;
					}
				}
			}
		}, PhoneStateListener.LISTEN_CALL_STATE);
	}

	private void readBleParams() {
		callsRemind = PreferenceUtil.readBoolean(this, C.sp.switch_phone_calls_reminding, true);
		locationShare = PreferenceUtil.readBoolean(this, C.sp.switch_location_alarm, true);
		lossPrevent = PreferenceUtil.readBoolean(this, C.sp.switch_location_alarm, true);
		recorder.recordConnectInfo("初始化参数配置[来电提醒"+callsRemind+";告警"+locationShare+";防丢"+lossPrevent+";]");
	}

	/** 快速挥动StrawRing 来拍摄照片 */
	private boolean thresholdOverflowOnCamera = false;
	/** 来电提示 */
	private boolean callsRemind = false;
	/** 紧急位置共享 */
	private boolean locationShare = false;
	/** 手机防丢 */
	private boolean lossPrevent = false;
	/** 来电闪灯时长 */
	private int lightTime = 30;
	/** 丢失闪灯时长 */
	private int lossFlashTime = 5;

	/** 设备交互逻辑控制器 */
	private RingBleController rbController = new RingBleController(new OnRingMessageReceivedListener() {
		/** 心跳包数量记录标识 */
		private int keepAliveIndex;

		@Override public void triggerMotionThreshold() {
			if (thresholdOverflowOnCamera) {
				broadcast(ACTION_GATT_MOTION_THRESHOLD_OVERFLOW);
				recorder.recordConnectInfo("收到消息：拍照");
			}
			else if (locationShare) {
				recorder.recordConnectInfo("收到消息：定位");
				sendAlarmMessage();
			}
		}

		@Override public void stepGauge(final String address, boolean hasMore, int t2000ToCurrent, int exerciseMode, short duration, short step) {
			dbRecordInfoToDailySummary(address, hasMore, t2000ToCurrent, exerciseMode, duration, step);
			recorder.recordConnectInfo("收到消息：记步[是否还有数据"+hasMore+";距离2000年秒数"+t2000ToCurrent+";运动模式"+exerciseMode+";持续时间"+duration+"分钟;步数"+step+";]");
			// 如果还存在数据; 继续抓取
			if (hasMore) {
				mHandler.postDelayed(new Runnable() {
					@Override public void run() {
						requestExerciseInfo(address, false);
					}
				}, 300);
			} else {
				mHandler.postDelayed(new Runnable() {
					@Override public void run() {
						broadcast(ACTION_GATT_EXERCISE_INFO_REPORT);
					}
				}, 300);
			}
		};

		@Override public void keepAlive(String address) {
			/*
			 * 手机APP在后面仍然隔一段时间就要向设备发送一下SET_TIMESTAMP消息，发送频率控制在半小时左右。<br>
			 * 可以利用原先设备和手机之间的KEEP ALIVE机制，在收到一定数量的心跳包之后，发送SET_TIMESTAMP消息。<br>
			 */
			recorder.recordConnectInfo("收到消息:心跳包["+keepAliveIndex+"]");
			keepAliveIndex++;
			if (keepAliveIndex % 30 == 0) {
				keepAliveIndex = 0;
				recorder.recordConnectInfo("收到消息:心跳包累计30次");
				requestAmendTimestamp(address);
			}
		}
	}, new OnRingUpgradeStepChangedListener() {
		@Override public void stepChanged(String address, int step) {
			if (UPGRADE_1 == step) {
				requestDeviceUpgrade(address, UPGRADE_2);
			}
			else if (UPGRADE_2 == step) {
//				requestDeviceUpgrade(address, UPGRADE_3);
				
			}
		}
	});

	private void dbRecordInfoToDailySummary(String address, boolean hasMore, int t2000ToCurrent, int exerciseMode, int duration, int step) {
		if(t2000ToCurrent < 100000000 || duration >= FormatUtil.todaySurplusSeconds()) {
			// 过滤问题数据; t2000ToCurrent 的值一般在4亿以上; 例如 490184847表示2015年7月14号早上10点左右
			// 过滤问题数据; 持续时间超过今天剩余分钟[FormatUtil.todaySurplusSeconds()]
			requestAmendTimestamp(address);
			return;
		}
		if(duration < 0 || step < 0) {
			// 过滤问题数据
			requestAmendTimestamp(address);
			return;
		}
		DailySummary dailySummary = App.i().getDailySummary();
		LogUtil.e("记录运动数据...");
		recorder.recordConnectInfo("记录运动数据...");
		Calories.handleIntance(t2000ToCurrent, exerciseMode, duration, step, dailySummary);
	}

	public void setThresholdOverflowOnCamera(boolean thresholdOverflowOnCamera) {
		this.thresholdOverflowOnCamera = thresholdOverflowOnCamera;
	}

	/**
	 * 设置设备基础信息
	 * 
	 * @param address
	 *            设备MAC地址
	 * @param callsRemind
	 *            是否开启来电提醒
	 * @param locationShare
	 *            是否开启地理位置信息共享
	 * @param lossPrevent
	 *            是否开启设备防丢
	 * @param lightTime
	 *            设备闪灯时长
	 * @param lossFlashTime
	 *            设备断开延时闪灯时长（用于规避闪断造成的设备闪灯）
	 */
	public void setDeviceBasicInfo(String address, boolean callsRemind, boolean locationShare, boolean lossPrevent, int lightTime,
			int lossFlashTime) {
		this.callsRemind = callsRemind;
		PreferenceUtil.write(this, C.sp.switch_phone_calls_reminding, callsRemind);
		this.locationShare = locationShare;
		PreferenceUtil.write(this, C.sp.switch_location_alarm, locationShare);
		this.lossPrevent = lossPrevent;
		PreferenceUtil.write(this, C.sp.switch_mobile_lost_proof, lossPrevent);
		this.lightTime = lightTime;
		PreferenceUtil.write(this, C.sp.switch_light_time, lightTime);
		this.lossFlashTime = lossFlashTime;
		PreferenceUtil.write(this, C.sp.switch_loss_time, lossFlashTime);

		requestBasicSettings(address, callsRemind, (byte) lightTime, locationShare, lossPrevent, (byte) lossFlashTime);
	}

	/** 地图定位服务 */
	private LocationManagerProxy aMapLocManager;
	private long lastLocationTime;

	@SuppressWarnings("deprecation") private void sendAlarmMessage() {
		if (!SystemTool.checkNet(this)) {
			LogUtil.e(getString(R.string.net_error));
			return;
		}

		long currTime =System.currentTimeMillis();
		/**Srun edit at 2015.9.2 start **/
		if (currTime - lastLocationTime < ALARM_LEAST_TIME) {
			LogUtil.d("间隔时间太短。避免频繁报警");
			return;
		}
		/**Srun edit at 2015.9.2 end **/
		lastLocationTime = currTime;

		aMapLocManager = LocationManagerProxy.getInstance(this);
		/*
		 * mAMapLocManager.setGpsEnable(false);//
		 * 1.0.2版本新增方法，设置true表示混合定位中包含gps定位，false表示纯网络定位，默认是true Location
		 * API定位采用GPS和网络混合定位方式
		 * ，第一个参数是定位provider，第二个参数时间最短是30000毫秒，第三个参数距离间隔单位是米，第四个参数是定位监听者
		 */
		LogUtil.d("aMapLocManager 定位中。。。");

		/**Srun edit at 2015.9.1 start **/
		if (!mIsLocationManagerRunning) {
			mIsFirstRun = false;
			aMapLocManager.requestLocationUpdates(LocationProviderProxy.AMapNetwork, 30000, 100, mAMapLocationListener);
		} else {
			alarm(mGeoLng, mGeoLat, mAccuracy);
		}
		/* 定位超时 */
//		mHandler.removeCallbacks(runReleaseAmpLocManager);
//		mHandler.postDelayed(runReleaseAmpLocManager, 12000);
		/**Srun edit at 2015.9.1 end **/
	}
	
	private Runnable runReleaseAmpLocManager = new Runnable() {
		@Override public void run() {
			releaseAmapLocManager();
		}
	};

	// 告警
	private void alarm(double lng, double lat, float accuracy) {
		PostEmergencyAlarmRequest alarmRequest = new PostEmergencyAlarmRequest();
		alarmRequest.msgid = C.request_msgid_post_emergency_alarm;
		alarmRequest.longitude = lng;
		alarmRequest.latitude = lat;
		alarmRequest.accuracy = accuracy;
		HttpUtil.requestJson(Method.POST, alarmRequest, new ResponeListener() {
			@Override
			public void onResponse(BaseResponse response, String resultStr) {
				if (response.retcode == 0) {
					broadcast(ACTION_GATT_MOTION_ALARM);
					showAlarmNotifcation();
				}
				LogUtil.e("alarm .retcode:" + response.retcode);
			}

			@Override public void onErrorResponse(Exception error) {
				LogUtil.e("alarm error:" + error.getMessage());
			}
		});
	}

	private AMapLocationListener mAMapLocationListener = new AMapLocationListener() {
		@Override public void onStatusChanged(String provider, int status, Bundle extras) {
		}

		@Override public void onProviderEnabled(String provider) {
		}

		@Override public void onProviderDisabled(String provider) {
		}

		@Override public void onLocationChanged(Location location) {
		}

		@Override public void onLocationChanged(AMapLocation location) {
			mHandler.removeCallbacks(runReleaseAmpLocManager);
			if (location != null) {
				/**Srun edit at 2015.9.1 start **/
				mIsLocationManagerRunning = true;
				mAccuracy = location.getAccuracy();
				mGeoLat = location.getLatitude();
				mGeoLng = location.getLongitude();
				String cityCode = "";
				String desc = "";
				Bundle locBundle = location.getExtras();
				if (locBundle != null) {
					cityCode = locBundle.getString("citycode");
					desc = locBundle.getString("desc");
				}
				String str = ("定位成功:(" + mGeoLng + "," + mGeoLat + ")" + "\n精    度    :" + location.getAccuracy() + "米" + "\n定位方式:"
						+ location.getProvider() + "\n定位时间:" + "\n城市编码:" + cityCode + "\n位置描述:" + desc + "\n省:" + location.getProvince()
						+ "\n市:" + location.getCity() + "\n区(县):" + location.getDistrict() + "\n区域编码:" + location.getAdCode());
				LogUtil.d(str);
				recorder.recordConnectInfo(str);
				if (!mIsFirstRun) {
					mIsFirstRun = true;
					alarm(mGeoLng, mGeoLat, location.getAccuracy());
				}
				
//				releaseAmapLocManager();
				/**Srun edit at 2015.9.1 end **/
			}
		}
		

	};
	

	@SuppressWarnings("deprecation") private void releaseAmapLocManager() {
		if (aMapLocManager != null) {
			aMapLocManager.removeUpdates(mAMapLocationListener);
			aMapLocManager.destory();
		}
		aMapLocManager = null;
	}

	private void showAlarmNotifcation(){
		NotificationManager mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
		//定义通知栏展现的内容信息
		int icon = R.drawable.ic_launcher;
//		CharSequence tickerText = "告警提示";
		CharSequence tickerText = getResources().getString(R.string.gaojing);
		long when = System.currentTimeMillis();
		Notification notification = new Notification(icon, tickerText, when);

		//定义下拉通知栏时要展现的内容信息
		Context context = getApplicationContext();
		CharSequence contentTitle = getResources().getString(R.string.gaojing);
		CharSequence contentText = getResources().getString(R.string.ninzai)+ FormatUtil.formatDate(new Date(),FormatUtil.HH_mm)+getResources().getString(R.string.xianghaoyou) ;
		PendingIntent contentIntent = PendingIntent.getActivity(RingBleService.this, 0,
				new Intent(), 0);
		notification.setLatestEventInfo(context, contentTitle, contentText,
				contentIntent);

		//用mNotificationManager的notify方法通知用户生成标题栏消息通知
		mNotificationManager.notify(1, notification);
	}

	private final Handler mHandler = new Handler();



	private void configPatchLen(int len,String address) {
		BluetoothGatt bluetoothGatt = getBluetoothGattByAddress(address);
		BluetoothGattService service = bluetoothGatt.getService(SERVICE_UPGRADE);
		BluetoothGattCharacteristic characteristic = service.getCharacteristic(CHARACTERISTIC_4_SPOTA_PATCH_LEN);


		characteristic.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT);
		characteristic.setValue(len,BluetoothGattCharacteristic.FORMAT_UINT16,0);
		bluetoothGatt.writeCharacteristic(characteristic);
	}
}
